/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pt.iasd.youthshelter.pathfinder;

import java.awt.Component;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.spi.actions.AbstractSavable;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.UndoRedo;
import org.openide.util.Lookup;
import org.openide.windows.TopComponent;
import org.openide.util.lookup.InstanceContent;
import pt.iasd.youthshelter.datamodel.Church;
import pt.iasd.youthshelter.datamodel.Pathfinder;
import pt.iasd.youthshelter.datamodel.service.ChurchController;
import pt.iasd.youthshelter.datamodel.service.PathfinderController;

/**
 * Top component which displays pathfinder editor window.
 */
//@ConvertAsProperties(
//        dtd = "-//pt.iasd.youthshelter.pathfinder//PathfinderEditor//EN",
//        autostore = false)
@TopComponent.Description(
        preferredID = "PathfinderEditorTopComponent",
        //iconBase="SET/PATH/TO/ICON/HERE", 
        persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "editor", openAtStartup = false)
//@ActionID(category = "Window", id = "pt.iasd.youthshelter.pathfinder.PathfinderEditorTopComponent")
//@ActionReference(path = "Menu/File/New" /*, position = 333 */)
//@TopComponent.OpenActionRegistration(
//        displayName = "#CTL_PathfinderEditorAction",
//        preferredID = "PathfinderEditorTopComponent")
//@Messages({
//    "CTL_PathfinderEditorAction=Pathfinder",
////    "CTL_PathfinderEditorTopComponent=New pathfinder",
////    "HINT_PathfinderEditorTopComponent=Pathfinder editor window."
//})
public final class PathfinderEditorTopComponent extends TopComponent {
    private static final ResourceBundle bundle = java.util.ResourceBundle.getBundle("pt/iasd/youthshelter/pathfinder/Bundle");
    
    private static final String TAG_BOLD_START = "<b>";
    private static final String TAG_BOLD_END = "</b>";
    private static final String TAG_HTML_START = "<html>";
    private static final String TAG_HTML_END = "</html>";
    
    private UndoRedo.Manager undoRedoManager = new UndoRedo.Manager();
    private InstanceContent instanceContent = new InstanceContent();
    private PathfinderSavable savable = new PathfinderSavable();
    
    /* Hidden Pathfinder atribute. */
//    private Pathfinder pathfinder = null;
    
    /* Hidden bean creation flag. */
    private boolean create = false;
    
    /* Logging object. */
    private Logger logger = Logger.getLogger(this.getClass().getName());
    
    public PathfinderEditorTopComponent(String pathfinderName) {
        initComponents();
        pathfinder = new Pathfinder();
        pathfinder.setName(pathfinderName);
        this.NameTextField.setText(pathfinderName);
        this.ActiveCheckBox.setSelected(true);
        create = true;
        setName(String.format("%s%s%s%s%s", TAG_HTML_START, TAG_BOLD_START,
                        pathfinderName, TAG_BOLD_END, TAG_HTML_END));
        setToolTipText(bundle.getString("PathfinderEditorTopComponent.Hint"));
        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
//        associateLookup(new AbstractLookup(instanceContent));
    }

    public PathfinderEditorTopComponent(Pathfinder pathfinder) {
        //TODO check if there's at least one church in the database.
        initComponents();
        create = (pathfinder == null);
        if(create) {
            setName(String.format("%s%s%s%s%s", TAG_HTML_START, TAG_BOLD_START,
                        bundle.getString("PathfinderEditorTopComponent.Title"),
                        TAG_BOLD_END, TAG_HTML_END));
        } else {
            setName(pathfinder.getName());
            this.pathfinder = pathfinder;
            this.NameTextField.setText(pathfinder.getName());
            this.BirthDatePicker.setDate(pathfinder.getStartActive());
            this.IDCardTextField.setText(pathfinder.getIdCard());
            this.ActiveCheckBox.setEnabled(pathfinder.getEndActive() == null);
            ChurchComboBox.setSelectedItem(pathfinder.getChurchId());
            if(pathfinder.getPhoneNumber() != null) {
                this.PhoneTextField.setValue(pathfinder.getPhoneNumber());
            }
            if(pathfinder.getCellphoneNumber() != null) {
                this.CellPhoneTextField.setValue(pathfinder.getCellphoneNumber());
            }
            if(pathfinder.getEmail() != null) {
                this.EmailTextField.setValue(pathfinder.getEmail());
            }
            undoRedoManager.discardAllEdits();
            valuesChanged();
        }
        setToolTipText(bundle.getString("PathfinderEditorTopComponent.Hint"));
        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
//        associateLookup(new AbstractLookup(instanceContent));
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        pathfinder = new pt.iasd.youthshelter.datamodel.Pathfinder();
        NameLabel = new javax.swing.JLabel();
        NameTextField = new javax.swing.JTextField();
        TopSeparator = new javax.swing.JSeparator();
        BirthLabel = new javax.swing.JLabel();
        BirthDatePicker = new org.jdesktop.swingx.JXDatePicker();
        IDCardLabel = new javax.swing.JLabel();
        IDCardTextField = new javax.swing.JTextField();
        ContactsLabel = new javax.swing.JLabel();
        PhoneLabel = new javax.swing.JLabel();
        CellPhoneLabel = new javax.swing.JLabel();
        EmailLabel = new javax.swing.JLabel();
        PhoneTextField = new javax.swing.JFormattedTextField(NumberFormat.getIntegerInstance());
        CellPhoneTextField = new javax.swing.JFormattedTextField(NumberFormat.getIntegerInstance());
        EmailTextField = new javax.swing.JFormattedTextField();
        ChurchLabel = new javax.swing.JLabel();
        ActiveCheckBox = new javax.swing.JCheckBox();
        ChurchComboBox = new javax.swing.JComboBox();

        org.openide.awt.Mnemonics.setLocalizedText(NameLabel, bundle.getString("PathfinderEditorTopComponent.NameLabel.text"));

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, pathfinder, org.jdesktop.beansbinding.ELProperty.create("${name}"), NameTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "NameBinding");
        bindingGroup.addBinding(binding);
        binding.bind();

        NameTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                NameTextFieldKeyReleased(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(BirthLabel, bundle.getString("PathfinderEditorTopComponent.BirthLabel.text"));

        BirthDatePicker.setMaximumSize(new java.awt.Dimension(130, 22));
        BirthDatePicker.setMinimumSize(new java.awt.Dimension(130, 22));
        BirthDatePicker.setPreferredSize(new java.awt.Dimension(130, 22));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, pathfinder, org.jdesktop.beansbinding.ELProperty.create("${birthday}"), BirthDatePicker, org.jdesktop.beansbinding.BeanProperty.create("date"), "BirthdayBinding");
        binding.setSourceNullValue(new Date());
        bindingGroup.addBinding(binding);
        binding.bind();
        BirthDatePicker.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BirthDatePickerActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(IDCardLabel, bundle.getString("PathfinderEditorTopComponent.IDCardLabel.text"));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, pathfinder, org.jdesktop.beansbinding.ELProperty.create("${idCard}"), IDCardTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "IDCardBinding");
        bindingGroup.addBinding(binding);
        binding.bind();

        IDCardTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                IDCardTextFieldKeyReleased(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(ContactsLabel, bundle.getString("PathfinderEditorTopComponent.ContactsLabel.text"));

        org.openide.awt.Mnemonics.setLocalizedText(PhoneLabel, bundle.getString("PathfinderEditorTopComponent.PhoneLabel.text"));

        org.openide.awt.Mnemonics.setLocalizedText(CellPhoneLabel, bundle.getString("PathfinderEditorTopComponent.CellPhoneLabel.text"));

        org.openide.awt.Mnemonics.setLocalizedText(EmailLabel, bundle.getString("PathfinderEditorTopComponent.EmailLabel.text"));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, pathfinder, org.jdesktop.beansbinding.ELProperty.create("${phoneNumber}"), PhoneTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "PhoneBinding");
        bindingGroup.addBinding(binding);
        binding.bind();

        PhoneTextField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                PhoneTextFieldPropertyChange(evt);
            }
        });

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, pathfinder, org.jdesktop.beansbinding.ELProperty.create("${cellphoneNumber}"), CellPhoneTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "CellPhoneBinding");
        bindingGroup.addBinding(binding);
        binding.bind();

        CellPhoneTextField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                CellPhoneTextFieldPropertyChange(evt);
            }
        });

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, pathfinder, org.jdesktop.beansbinding.ELProperty.create("${email}"), EmailTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "EmailBinding");
        bindingGroup.addBinding(binding);
        binding.bind();

        EmailTextField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                EmailTextFieldPropertyChange(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(ChurchLabel, bundle.getString("PathfinderEditorTopComponent.ChurchLabel.text"));

        org.openide.awt.Mnemonics.setLocalizedText(ActiveCheckBox, bundle.getString("PathfinderEditorTopComponent.ActiveCheckBox.text"));
        ActiveCheckBox.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        ActiveCheckBox.setFocusable(false);
        ActiveCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ActiveCheckBoxActionPerformed(evt);
            }
        });

        List<Church> churches = loadChurchComboBoxData();
        ChurchComboBox.setModel((churches == null || churches.isEmpty())? new DefaultComboBoxModel() : new DefaultComboBoxModel(churches.toArray(new Church[churches.size()])));
        ChurchComboBox.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        ChurchComboBox.setRenderer(new ChurchRenderer());
        if(!churches.isEmpty()) {
            ChurchComboBox.setSelectedIndex(0);
            pathfinder.setChurchId(churches.get(0));
        }
        ChurchComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ChurchComboBoxActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(PhoneLabel)
                            .addComponent(CellPhoneLabel)
                            .addComponent(EmailLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(PhoneTextField)
                            .addComponent(CellPhoneTextField)
                            .addComponent(EmailTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(NameLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(NameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 580, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(ContactsLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(TopSeparator))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(BirthLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(BirthDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addComponent(IDCardLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(IDCardTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 230, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(0, 0, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(ChurchLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(ChurchComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGap(18, 18, 18)
                                .addComponent(ActiveCheckBox)))
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(NameLabel)
                    .addComponent(NameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(BirthLabel)
                    .addComponent(BirthDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(IDCardLabel)
                    .addComponent(IDCardTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(ChurchLabel)
                    .addComponent(ActiveCheckBox)
                    .addComponent(ChurchComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(ContactsLabel)
                    .addComponent(TopSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(PhoneLabel)
                    .addComponent(PhoneTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(CellPhoneLabel)
                    .addComponent(CellPhoneTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(EmailLabel)
                    .addComponent(EmailTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        NameTextField.getDocument().addUndoableEditListener(undoRedoManager);
        IDCardTextField.getDocument().addUndoableEditListener(undoRedoManager);
        PhoneTextField.getDocument().addUndoableEditListener(undoRedoManager);
        CellPhoneTextField.getDocument().addUndoableEditListener(undoRedoManager);
        EmailTextField.getDocument().addUndoableEditListener(undoRedoManager);
        ActiveCheckBox.setSelected(pathfinder.getStartActive() != null && pathfinder.getEndActive() == null);

        bindingGroup.bind();
    }// </editor-fold>//GEN-END:initComponents

    private void NameTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_NameTextFieldKeyReleased
//        if(pathfinder == null) {
//            valuesChanged();
//        } else if(!pathfinder.getName().equals(NameTextField.getText())) {
            valuesChanged();
//        }
    }//GEN-LAST:event_NameTextFieldKeyReleased

    private void BirthDatePickerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BirthDatePickerActionPerformed
//        if(pathfinder == null) {
//            valuesChanged();
//        } else if(pathfinder.getBirthday().compareTo(BirthDatePicker.getDate()) != 0) {
            valuesChanged();
//        }
    }//GEN-LAST:event_BirthDatePickerActionPerformed

    private void IDCardTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_IDCardTextFieldKeyReleased
//        if(pathfinder == null) {
//            valuesChanged();
//        } else if(!pathfinder.getIdCard().equals(IDCardTextField.getText())) {
            valuesChanged();
//        }
    }//GEN-LAST:event_IDCardTextFieldKeyReleased

    private void ActiveCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ActiveCheckBoxActionPerformed
        if(pathfinder == null) {
            valuesChanged();
        } else {
            if(pathfinder.getEndActive() == null) {
                if(!ActiveCheckBox.isSelected()) {
                    valuesChanged();
                }
            } else {
                if(ActiveCheckBox.isSelected()) {
                    valuesChanged();
                }
            }
        }
    }//GEN-LAST:event_ActiveCheckBoxActionPerformed

    private void ChurchComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ChurchComboBoxActionPerformed
        if(pathfinder == null) {
            valuesChanged();
        } else if(pathfinder.getChurchId() == null ||
                pathfinder.getChurchId().getId() != ((Church)ChurchComboBox.getSelectedItem()).getId()) {
            valuesChanged();
        }
    }//GEN-LAST:event_ChurchComboBoxActionPerformed

    private void PhoneTextFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_PhoneTextFieldPropertyChange
//        if(pathfinder == null) {
//            valuesChanged();
//        } else if(pathfinder.getPhoneNumber() != Integer.parseInt(PhoneTextField.getText())) {
            valuesChanged();
//        }
    }//GEN-LAST:event_PhoneTextFieldPropertyChange

    private void CellPhoneTextFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_CellPhoneTextFieldPropertyChange
//        if(pathfinder == null) {
//            valuesChanged();
//        } else if(pathfinder.getCellphoneNumber() != Integer.parseInt(CellPhoneTextField.getText())) {
            valuesChanged();
//        }
    }//GEN-LAST:event_CellPhoneTextFieldPropertyChange

    private void EmailTextFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_EmailTextFieldPropertyChange
//        if(pathfinder == null) {
//            valuesChanged();
//        } else if(!pathfinder.getEmail().equals(EmailTextField.getText())) {
            valuesChanged();
//        }
    }//GEN-LAST:event_EmailTextFieldPropertyChange
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox ActiveCheckBox;
    private org.jdesktop.swingx.JXDatePicker BirthDatePicker;
    private javax.swing.JLabel BirthLabel;
    private javax.swing.JLabel CellPhoneLabel;
    private javax.swing.JFormattedTextField CellPhoneTextField;
    private javax.swing.JComboBox ChurchComboBox;
    private javax.swing.JLabel ChurchLabel;
    private javax.swing.JLabel ContactsLabel;
    private javax.swing.JLabel EmailLabel;
    private javax.swing.JFormattedTextField EmailTextField;
    private javax.swing.JLabel IDCardLabel;
    private javax.swing.JTextField IDCardTextField;
    private javax.swing.JLabel NameLabel;
    private javax.swing.JTextField NameTextField;
    private javax.swing.JLabel PhoneLabel;
    private javax.swing.JFormattedTextField PhoneTextField;
    private javax.swing.JSeparator TopSeparator;
    private pt.iasd.youthshelter.datamodel.Pathfinder pathfinder;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables
    
    @Override
    public boolean canClose() {
        Collection<? extends PathfinderSavable> savables = getLookup().lookupAll(PathfinderSavable.class);
        if(savables != null && savables.contains(savable)) {
            NotifyDescriptor.Confirmation confirm = new NotifyDescriptor.Confirmation(
                    bundle.getString("Confirmation.Editor.Message")
                            .replace("\n", System.getProperty("line.separator")),
                    bundle.getString("Confirmation.Editor.Title")
            );
            Object option = DialogDisplayer.getDefault().notify(confirm);
            if(option == NotifyDescriptor.YES_OPTION) {
                savable.handleSave();
                return true;
            } else if(option == NotifyDescriptor.NO_OPTION) {
                savable.cancelSave();
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // read your settings according to their version
    }
    
    private void valuesChanged() {
        if(undoRedoManager.canUndo()) {
            if(getLookup().lookup(PathfinderSavable.class) == null) {
                if(ChurchComboBox.getSelectedItem() == null) {
                    NotifyDescriptor dialog = new NotifyDescriptor(bundle.getString("NoChurchSelected.Error")
                            .replace("\n", System.getProperty("line.separator")),
                    bundle.getString("NoChurch.Title"), NotifyDescriptor.ERROR_MESSAGE,
                    NotifyDescriptor.ERROR_MESSAGE, null, null);
                    DialogDisplayer.getDefault().notify(dialog);
                } else {
                    instanceContent.remove(savable);
                    instanceContent.add(savable);
                }
            }
            setName(String.format("%s%s%s%s%s", TAG_HTML_START, TAG_BOLD_START,
                    (NameTextField.getText().isEmpty())? getName() : NameTextField.getText(),
                    TAG_BOLD_END, TAG_HTML_END));
        } else {
            instanceContent.remove(savable);
            setName(((NameTextField.getText().isEmpty())? getDefaultName() : NameTextField.getText()));
        }
    }

    @Override
    public UndoRedo getUndoRedo() {
        return undoRedoManager;
    }
    
    private String getDefaultName() {
        return bundle.getString("PathfinderEditorTopComponent.Title");
    }
    
    // <editor-fold defaultstate="collapsed" desc="Inner Classes">
    private class PathfinderSavable extends AbstractSavable {
        public PathfinderSavable() {
            register();
        }
        
        public void cancelSave() {
            instanceContent.remove(this);
            unregister();
        }
        
        @Override
        protected String findDisplayName() {
            return getName();
        }

        @Override
        protected void handleSave() {
            /* Check not null requirements */
            if(NameTextField.getText() == null || NameTextField.getText().isEmpty()) {
                NotifyDescriptor.Message alert = new NotifyDescriptor.Message(
                        bundle.getString("NoPathfinderName.Error")
                                .replace("\n", System.getProperty("line.separator")),
                        NotifyDescriptor.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(alert);
                return;
            }
            if(IDCardTextField.getText() == null || IDCardTextField.getText().isEmpty()) {
                NotifyDescriptor.Message alert = new NotifyDescriptor.Message(
                        bundle.getString("NoPathfinderIDCard.Error")
                                .replace("\n", System.getProperty("line.separator")),
                        NotifyDescriptor.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(alert);
                return;
            }
            
            /* Create progress bar handle */
            ProgressHandle pHandle = ProgressHandleFactory.createHandle(
                    bundle.getString("ProgressBarSave"));
            pHandle.start(3);
            
            /* Set pathfinder parameters. */
            pathfinder.setName(NameTextField.getText());
            pathfinder.setIdCard(IDCardTextField.getText());
            pathfinder.setChurchId((Church)ChurchComboBox.getSelectedItem());
            pathfinder.setStartActive(BirthDatePicker.getDate());
            if(PhoneTextField.getValue() != null) {
                pathfinder.setPhoneNumber(((Long)PhoneTextField.getValue()).intValue());
            }
            if(CellPhoneTextField.getValue() != null) {
                pathfinder.setCellphoneNumber(((Long)CellPhoneTextField.getValue()).intValue());
            }
            if(EmailTextField.getText() != null) {
                pathfinder.setEmail(EmailTextField.getText());
            }
            if(ActiveCheckBox.isSelected()) {
                pathfinder.setEndActive(null);
            } else {
                pathfinder.setEndActive(new Date());
            }
            pHandle.progress(1);
            
            /* Persist pathfinder in database. */
            PathfinderController controller = Lookup.getDefault().lookup(PathfinderController.class);
            if(controller != null) {
                try{
                    if(create) {
                        controller.create(pathfinder);
                    } else {
                        controller.edit(pathfinder);
                    }
                } catch(Exception ex) {
                    logger.log(Level.WARNING, ex.getLocalizedMessage(), ex);
                }
            }
            pHandle.progress(1);
            
            /* Remove this savable from lookup. */
            instanceContent.remove(this);
            setName(pathfinder.getName());
            unregister();
            pHandle.progress(1);
            pHandle.finish();
        }

        @Override
        public boolean equals(Object o) {
            if(o instanceof PathfinderSavable) {
                return this == (PathfinderSavable) o;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return PathfinderEditorTopComponent.this.hashCode();
        }
    }
    
    private class ChurchRenderer extends BasicComboBoxRenderer {
        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if(value instanceof Church) {
                setText(((Church)value).getName());
            } else {
                setText("");
            }
            return this;
        }
    } // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="ComboBox Data Loading Code">
    private List loadChurchComboBoxData() {
        ChurchController controller = Lookup.getDefault().lookup(ChurchController.class);
        if(controller != null) {
            try{
                List list = controller.findChurchEntities();
                if(!list.isEmpty()) {
                    return list;
                }
            } catch(Exception ex) {
                logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
            }
        }
        return null;
    }// </editor-fold>
}
